#include <glf/config.h>
#include <cmath>
#include <glf/core/inlines.h>

namespace glf {

float Log(float);
double Log(double);

namespace math_detail {

template <typename T>
inline T DegToRad(T x) {
	return x * T(0.0174532925);
}

template <typename T>
inline T RadToDeg(T x) {
	return x * T(57.2957795);
}

template <typename T>
inline T Sin(T x) {
	return std::sin(x);
}

template <typename T>
inline T Cos(T x) {
	return std::cos(x);
}

template <typename T>
inline T Tan(T x) {
	return std::tan(x);
}

template <typename T>
inline T Acos(T x) {
	return std::acos(x);
}

template <typename T>
inline T SafeAcos(T x) {
	return std::acos(Clamp(x, T(-1), T(1)));
}

template <typename T>
inline T Asin(T x) {
	return std::asin(x);
}

template <typename T>
inline T SafeAsin(T x) {
	return std::asin(Clamp(x, T(-1), T(1)));
}

template <typename T>
inline T Atan(T x) {
	return std::atan(x);
}

template <typename T>
inline T Atan2(T y, T x) {
	return std::atan2(y, x);
}

template <typename T>
inline T Sqrt(T x) {
	return std::sqrt(x);
}

inline int Sqrt(int x) {
	int sqrt = 0;

	for(int i = 0x10000000; i != 0; i >>= 2) {
		int temp = sqrt + i;
		sqrt >>= 1;
	
		if(temp <= x) {
			x -= temp;
			sqrt += i;
		}
	}

	return sqrt;
}

template <typename T>
inline T Fmod(T x, T y) {
	return std::fmod(x, y);
}

template <typename T>
inline T Ceil(T x) {
	return std::ceil(x);
}

template <typename T>
inline T Floor(T x) {
	return std::floor(x);
}

template <typename T>
inline T Log(T x) {
	return std::log(x);
}

template <typename T>
inline T Log10(T x) {
	return glf::Log(x) / glf::Log(T(10));
}

inline int Log10(int x) {
	return (int)(glf::Log(float(x)) / glf::Log(10.f));
}

} //namespace math_detail
} //namespace glf
